package com.yboot.framework.plugin.generator.service;

import com.yboot.framework.plugin.generator.entity.GenTable;
import com.yboot.framework.plugin.generator.entity.GenTableColumn;
import com.yboot.framework.plugin.generator.mapper.GeneratorMapper;
import com.yboot.framework.plugin.generator.property.CodeGenProperty;
import com.yboot.framework.plugin.generator.utils.CodeGenUtil;
import com.yboot.framework.plugin.generator.utils.ConvertUtil;
import com.yboot.framework.plugin.generator.utils.TypeUtils;
import com.yboot.framework.plugin.generator.utils.VelocityUtil;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.WordUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.List;

/**
 * @author .
 * @date 2022-11-10
 */
@Service
public class GeneratorService {

    private Logger logger = LoggerFactory.getLogger(getClass());

    private final GeneratorMapper mapper;

    private final CodeGenProperty property;

    public GeneratorService(GeneratorMapper mapper, CodeGenProperty property) {
        this.mapper = mapper;
        this.property = property;
    }

    public void generate() {
        String tableName = property.getTable().getName();
        GenTable table = mapper.queryTable(tableName, property.getTable().getSchema());
        List<GenTableColumn> columns = mapper.queryColumns(tableName, property.getTable().getSchema());

        initGenColumn(columns);

        initGenTable(table, columns);

        VelocityUtil.initVelocity();

        VelocityContext context = VelocityUtil.prepareContext(property, table);

        for (String template : CodeGenUtil.getTemplates()) {
            if (!CodeGenUtil.skip(template, property)) {
                //渲染模板
                StringWriter sw = new StringWriter();
                Template tpl = Velocity.getTemplate(template, "UTF-8");
                tpl.merge(context, sw);

                String savePath = CodeGenUtil.getSavePath(template, property, table.getClassName());

                saveLocal(savePath, sw.getBuffer());
            } else {
                logger.info("跳过文件：" + template);
            }
        }

    }

    private void setPkColumn(GenTable table, List<GenTableColumn> columns) {
        for (GenTableColumn co : columns) {
            if (co.getColumnKey().equals(GenTableColumn.COLUMN_KEY_PRI)) {
                table.setPkColumn(co);
                break;
            }
        }
    }

    private void initGenColumn(List<GenTableColumn> columns) {
        for (GenTableColumn column : columns) {
            column.setJavaField(columnToJavaField(column.getColumnName()));
            column.setJavaType(TypeUtils.getJavaType(column.getColumnType()));
            column.setValidatorName(TypeUtils.getValidator(column.getJavaType()));
            // 标记列，是否是查询参数
            column.setSearchable(property.getGenOption().getSearchColumns().contains(column.getColumnName()));
        }
    }

    private String columnToJavaField(String columnName) {
        return ConvertUtil.lineToHump(columnName);
    }

    private void initGenTable(GenTable table, List<GenTableColumn> columns) {

        String prefix = property.getTable().getPrefix();

        String tableName = table.getTableName();

        if (StringUtils.isNotBlank(prefix)) {
            tableName = tableName.replaceFirst(prefix, "");
        }
        String className = WordUtils.capitalizeFully(tableName, new char[]{'_'}).replace("_", "");

        table.setClassName(className);
        setPkColumn(table, columns);
        table.setColumns(columns);
    }

    public void saveLocal(String savePath, StringBuffer sb) {

        File target = new File(savePath);
        if (!target.exists() || property.getGenOption().isOverrideFile()) {
            try {
                FileUtils.writeStringToFile(target, String.valueOf(sb), "UTF-8");
                logger.info(savePath + "渲染成功");
            } catch (IOException e) {
                logger.info(savePath + "保存失败. e = " + e.getMessage());
            }
        } else {
            logger.info(savePath + "已经存在");
        }

    }

}
